#include"ThreadCache.hpp"
#include"CentralCache.hpp"
#pragma once
void* ThreadCache::Allocate(size_t size)
{
    size_t bytes=SizeClass::Roundup(size);
    size_t index=SizeClass::Index(size);
    void* obj;
    if(!_freeLists[index].Empty())
    {
        return _freeLists[index].Pop();
    }
    else
    {
       obj=FetchFromCentralCache(index,bytes);
    }
    return obj;
}
void ThreadCache::Deallocate(void* ptr,size_t size)
{
    assert(ptr);
    assert(size<=MAX_BYTES);
    size_t index=SizeClass::Index(size);
    _freeLists[index].Push(ptr);

	if(_freeLists[index].Size()>=_freeLists[index].MaxSize())	//处理单个threadCache链表长度过长的情况
	{
		ListTooLong(_freeLists[index],size);
	}
}
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
	//	慢开始反馈调节法		不会开始要太多内存
	size_t	batchNum = std::min(_freeLists[index].MaxSize(), SizeClass::NumMoveSize(size));

	if (batchNum == _freeLists[index].MaxSize())
	{
		++_freeLists[index].MaxSize();
	}

	void* start = nullptr;
	void* end = nullptr;
	size_t actualNum = CentralCache::GetInstance()->FetchRangeObj(start, end, batchNum, size);	//	获取连续实际内存的数目
	assert(actualNum >= 1);	//	至少一个

	if (actualNum == 1)
	{
		assert(start == end);
	}
	else
	{
		_freeLists[index].PushRange(NextObj(start), end,actualNum-1);   
	}

	return start;
}
void ThreadCache::ListTooLong(FreeList& list, size_t size)
{
	void* start=nullptr;
	void* end=nullptr;
	list.PopRange(start,end,list.MaxSize());
	
	CentralCache::GetInstance()->ReleaseListToSpans(start,size);
}